#include "string.h"
#include <limits.h>
#include <stdlib.h>
//#include "fcan.h"
//#include "fcan_hw.h"
#include "fcan_simple.h"
#include "fassert.h"
#include "fswap.h"
#include "fparameters.h"
#include "fdrivers_port.h"

#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi)
#define do_div(n, base) (                 \
{                                     \
    uint32_t __base = (base);         \
    uint32_t __rem;                   \
    __rem = ((uint64_t)(n)) % __base; \
    (n) = ((uint64_t)(n)) / __base;   \
    __rem;                            \
})

#define FCAN_READ_REG32(addr, reg_offset) FtIn32((addr) + (u32)(reg_offset))
#define FCAN_WRITE_REG32(addr, reg_offset, reg_value) FtOut32((addr) + (u32)reg_offset, (u32)reg_value)
#define FCAN_SETBIT(base_addr, reg_offset, data)      FtSetBit32((base_addr) + (u32)(reg_offset), (u32)(data))
#define FCAN_CLEARBIT(base_addr, reg_offset, data)     FtClearBit32((base_addr) + (u32)(reg_offset), (u32)(data))

typedef struct
{
    u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
    u32 tseg1_max;
    u32 tseg2_min; /* Time segement 2 = phase_seg2 */
    u32 tseg2_max;
    u32 sjw_max; /* Synchronisation jump width */
    u32 brp_min; /* Bit-rate prescaler */
    u32 brp_max;
    u32 brp_inc;
} FCanBittimingConst;

/* 仲裁段速率默认值 */
static const FCanBittimingConst FCanArbBitConst =
{
    .tseg1_min = FCAN_ARB_TSEG1_MIN, /* Time segement 1 = prop_seg + phase_seg1 */
    .tseg1_max = FCAN_ARB_TSEG1_MAX,
    .tseg2_min = FCAN_ARB_TSEG2_MIN, /* Time segement 2 = phase_seg2 */
    .tseg2_max = FCAN_ARB_TSEG2_MAX,
    .sjw_max = FCAN_ARB_SJW_MAX, /* Synchronisation jump width */
    .brp_min = FCAN_ARB_BRP_MIN, /* Bit-rate prescaler */
    .brp_max = FCAN_ARB_BRP_MAX,
    .brp_inc = FCAN_ARB_BRP_INC,
};

/* 数据段速率默认值 */
static const FCanBittimingConst FCanDataBitConst =
{
    .tseg1_min = FCAN_DATA_TSEG1_MIN, /* Time segement 1 = prop_seg + phase_seg1 */
    .tseg1_max = FCAN_DATA_TSEG1_MAX,
    .tseg2_min = FCAN_DATA_TSEG2_MIN, /* Time segement 2 = phase_seg2 */
    .tseg2_max = FCAN_DATA_TSEG2_MAX,
    .sjw_max = FCAN_DATA_SJW_MAX, /* Synchronisation jump width */
    .brp_min = FCAN_DATA_BRP_MIN, /* Bit-rate prescaler */
    .brp_max = FCAN_DATA_BRP_MAX,
    .brp_inc = FCAN_DATA_BRP_INC,
};

const FCanConfig FCanConfigTbl[FCAN_NUM] =
{
    {
        .instance_id = FCAN0_ID, /* Id of device */
        .base_address = FCAN0_BASE_ADDR,  /* Can base Address */
        .caps = FCAN_CAPACITY,
    },
    {
        .instance_id = FCAN1_ID, /* Id of device */
        .base_address = FCAN1_BASE_ADDR,  /* Can base Address */
        .caps = FCAN_CAPACITY,
    }
};

static uint32_t FCanGetDlcLen(uint32_t dlc) {
    static const uint32_t dlc_table[16] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64
    };
    return (dlc < 16) ? dlc_table[dlc] : 0;
}

static uint32_t FCanSetDlcLen(uint32_t dlc_len) {
    for (uint32_t i = 0; i < 16; i++) {
        if (FCanGetDlcLen(i) == dlc_len) return i;
    }
    return 0;
}

/* calculate the can sample point */
static s32 FCanUpdateSamplePoint(const FCanBittimingConst *btc,
                                 u32 sample_point_nominal, u32 tseg,
                                 u32 *tseg1_ptr, u32 *tseg2_ptr,
                                 u32 *sample_point_error_ptr)
{
    u32 sample_point_error, best_sample_point_error = UINT_MAX;
    u32 sample_point, best_sample_point = 0;
    u32 tseg1, tseg2;
    s32 i;

    for (i = 0; i <= 1; i++)
    {
        tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i;
        tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
        tseg1 = tseg - tseg2;
        if (tseg1 > btc->tseg1_max)
        {
            tseg1 = btc->tseg1_max;
            tseg2 = tseg - tseg1;
        }

        sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG);
        sample_point_error = abs(sample_point_nominal - sample_point);

        if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error))
        {
            best_sample_point = sample_point;
            best_sample_point_error = sample_point_error;
            *tseg1_ptr = tseg1;
            *tseg2_ptr = tseg2;
        }
    }

    if (sample_point_error_ptr)
    {
        *sample_point_error_ptr = best_sample_point_error;
    }

    return best_sample_point;
}

/**
 * @name: FCanCalcBittiming
 * @msg:  This routine calculate Bit timing
 * @param {structFCanBittiming} *bt_p is is a structure that contains the CAN baud rate configuration parameter , The user needs to fill in the baudrate first
 * @param {u32} target_baudrate, parameters of target baudrate
 * @param {u32} target_sample_point, parameters of target sample point, 0 means the general configuration is used
 * @param {FCanSegmentType} target_segment, specifies which target is to be selected. followed by FCAN_ARB_SEGMENT or FCAN_DATA_SEGMENT
 * @return err code information, FCAN_SUCCESS indicates success，others indicates failed
 */
static FError FCanCalcBittiming(FCanBaudrateConfig *bt_p, u32 target_baudrate, u32 target_sample_point, FCanSegmentType target_segment)
{
    u32 baudrate;       /* current baudrate */
    u32 baudrate_error; /* difference between current and nominal value */
    u32 best_baudrate_error = UINT_MAX;
    u32 sample_point_error; /* difference between current and nominal value */
    u32 best_sample_point_error = UINT_MAX;
    u32 sample_point_nominal; /* nominal sample point */
    u32 best_tseg = 0;        /* current best value for tseg */
    u32 best_brp = 0;         /* current best value for brp */
    u32 brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
    u64 v64;
    u32 reg_val;

    const FCanBittimingConst *btc;
    FCanBaudrateConfig *bt = bt_p;

    if (target_segment == FCAN_DATA_SEGMENT)
    {
        btc = &FCanDataBitConst;
    }
    else
    {
        btc = &FCanArbBitConst;
    }

    if (target_sample_point)
    {
        printf("\n enter if (target_sample_point)\n");
        sample_point_nominal = target_sample_point;
    }
    else
    {
        if (target_baudrate > 4000000)
        {
            sample_point_nominal = 650;
        }
        else if (target_baudrate > 2000000)
        {
            sample_point_nominal = 680;
        }
        else if (target_baudrate > 1000000)
        {
            sample_point_nominal = 725;
        }
        else if (target_baudrate > 800000)
        {
            printf("\n enter else if (target_baudrate > 800000)\n");
            sample_point_nominal = 750;
        }
        else if (target_baudrate > 500000)
        {
            sample_point_nominal = 800;
        }
        else
        {
            sample_point_nominal = 875;
        }
    }

    for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
         tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--)
    {
        tsegall = CAN_CALC_SYNC_SEG + tseg / 2;

        /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
        brp = FCAN_CLK_FREQ_HZ / (tsegall * target_baudrate) + tseg % 2;

        /* choose brp step which is possible in system */
        brp = (brp / btc->brp_inc) * btc->brp_inc;

        if ((brp < btc->brp_min) || (brp > btc->brp_max))
        {
            continue;
        }

        baudrate = FCAN_CLK_FREQ_HZ / (brp * tsegall);
        baudrate_error = abs(target_baudrate - baudrate);

        /* tseg brp biterror */
        if (baudrate_error > best_baudrate_error)
        {
            continue;
        }

        /* reset sample point error if we have a better baudrate */
        if (baudrate_error < best_baudrate_error)
        {
            best_sample_point_error = UINT_MAX;
        }

        FCanUpdateSamplePoint(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error);

        u32 prop_seg = tseg1 / 2;
        u32 phase_seg1 = tseg1 - prop_seg;
        u32 phase_seg2 = tseg2;
        u32 sjw = 1;

        /* Setting Baud Rate prescalar value in BRPR Register */
        reg_val = (brp - 1) << 16;
        reg_val |= (prop_seg - 1) << 2;
        reg_val |= (phase_seg1 - 1) << 5;
        reg_val |= (phase_seg2 - 1) << 8;
        reg_val |= (sjw - 1);

        if (sample_point_error > best_sample_point_error)
        {
            continue;
        }

        best_sample_point_error = sample_point_error;
        best_baudrate_error = baudrate_error;
        best_tseg = tseg / 2;
        best_brp = brp;

        if (baudrate_error == 0 && sample_point_error == 0)
        {
            break;
        }
    }

    if (best_baudrate_error)
    {
        /* Error in one-tenth of a percent */
        v64 = (u64)best_baudrate_error * 1000;
        do_div(v64, target_baudrate);
        baudrate_error = (u32)v64;
        if (baudrate_error > CAN_CALC_MAX_ERROR)
        {
            return FCAN_FAILURE;
        }
    }

    /* real sample point */
    FCanUpdateSamplePoint(btc, sample_point_nominal, best_tseg,
                          &tseg1, &tseg2, NULL);

    bt->prop_seg = tseg1 / 2;
    bt->phase_seg1 = tseg1 - bt->prop_seg;
    bt->phase_seg2 = tseg2;

    /* check for sjw user settings */
    if (!bt->sjw || !btc->sjw_max)
    {
        bt->sjw = 1;
    }
    else
    {
        /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
        if (bt->sjw > btc->sjw_max)
        {
            bt->sjw = btc->sjw_max;
        }
        /* bt->sjw must not be higher than tseg2 */
        if (tseg2 < bt->sjw)
        {
            bt->sjw = tseg2;
        }
    }

    bt->brp = best_brp;

     /* real baudrate */
    if (target_baudrate != FCAN_CLK_FREQ_HZ / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2)))
    {
        printf("\nTarget baudrate calculate timing failed.\n");
        return FCAN_FAILURE;
    }

    return FCAN_SUCCESS;
}

/**
 * @name: FCanReset
 * @msg: reset a specific can instance
 * @param {FCanCtrl} *pctrl, instance of FCan controller
 * @return {*}
 */
void FCanReset(FCanCtrl *instance_p)
{
    u32 reg_value;
    FCanConfig *config_p;
    config_p = &instance_p->config;

    FCAN_WRITE_REG32(config_p->base_address, FCAN_CTRL_OFFSET, 0);
    reg_value = FCAN_READ_REG32(config_p->base_address, FCAN_CTRL_OFFSET);
    if (reg_value & FCAN_CTRL_XFER_MASK)
    {
        printf("\n Can is not in configration mode.\n");
        return;
    }

    /* reset can */
    FCAN_WRITE_REG32(config_p->base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_RST_MASK);
    return;
}

/**
 * @name: FCanDeInitialize
 * @msg: Deinitializes a specific can instance
 * @param {FCanCtrl} *pctrl, instance of FCan controller
 * @return {*}
 */
void FCanDeInitialize(FCanCtrl *instance_p)
{
    instance_p->is_ready = 0;
    memset(instance_p, 0, sizeof(*instance_p));
    return;
}

const FCanConfig *FCanLookupConfig(u32 instance_id)
{
    const FCanConfig *pconfig = NULL;
    u32 index;

    for (index = 0; index < (u32)FCAN_NUM; index++)
    {
        if (FCanConfigTbl[index].instance_id == instance_id)
        {
            pconfig = &FCanConfigTbl[index];
            break;
        }
    }
    return (const FCanConfig *)pconfig;
}

/**
 * @name: FCanCfgInitialize
 * @msg:  Initializes a specific instance such that it is ready to be used.
 * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
 * @param {FCanConfig} *input_config_p, configuration parameters of FCanCtrl
 * @return err code information, FCAN_SUCCESS indicates success，others indicates failed
 */
FError FCanCfgInitialize(FCanCtrl *instance_p, const FCanConfig *input_config_p)
{
    FError ret = FCAN_SUCCESS;

    /*Set default values and configuration data */
    FCanDeInitialize(instance_p);

    instance_p->config = *input_config_p;

    instance_p->is_ready = FT_COMPONENT_IS_READY;

    FCanReset(instance_p);

    return ret;
}

/**
 * @name: FCanRecv
 * @msg: receive can message by specific can instance.
 * @param {FCanCtrl} *instance_p, pointer to a FCanCtrl structure that contains
 *                the configuration information for the specific can module.
 * @param {FCanFrame} *frame_p, can message receive struct.
 * @return err code information, FCAN_SUCCESS indicates success，others indicates failed.
 */
FError FCanRecv(FCanCtrl *instance_p, FCanFrame *frame_p)
{
    u32 canid;
    u32 dlc;
    int i = 0, j = 0;
    uintptr base_address = instance_p->config.base_address;

    memset(frame_p, 0, sizeof(FCanFrame));

    /* Read a frame from Phytium CAN */
    canid = FCAN_READ_REG32(base_address, FCAN_RX_FIFO_OFFSET);
    /* if canid is big-endian ,use swap change to little-endian */
    canid = be32_to_cpu(canid);

    if (canid & FTCANFD_ID1_FDL_MASK)
    {
        printf ("\n enter canid & FTCANFD_ID1_FDL_MASK \n");
        if (canid & FTCANFD_ID1_BRS_MASK)
        {
            frame_p->flags |= CANFD_BRS;
        }

        if (canid & FTCANFD_ID1_ESI_MASK)
        {
            frame_p->flags |= CANFD_ESI;
        }
        dlc = FTCANFD_ID1_SDLC_GET(canid);
    }
    else
    {
        dlc = FCAN_IDR_DLC_GET(canid);
    }

    /* The received frame is a standard format frame */
    frame_p->canid = FCAN_IDR_ID1_GET(canid);
    if (canid & FCAN_IDR_SRR_MASK)
    {
        printf("\n enter  if (canid & FCAN_IDR_SRR_MASK) \n");
        frame_p->canid |= CAN_RTR_FLAG;
    }

    frame_p->candlc = FCanGetDlcLen(dlc);

    if (!(frame_p->canid & CAN_RTR_FLAG))
    {
        j = 0;
        for (i = frame_p->candlc; i > 0; i -= 4)
        {
            *(u32 *)(frame_p->data + j) = FCAN_READ_REG32(base_address, FCAN_RX_FIFO_OFFSET);
            j += 4;
        }

        if (i > 0)
        {
            *(u32 *)(frame_p->data + j) = FCAN_READ_REG32(base_address, FCAN_RX_FIFO_OFFSET);
        }
    }

    return FCAN_SUCCESS;
}

u32 FCanFrameToBuf(FCanCtrl *instance_p, FCanFrame *frame_p, u32 *buf)
{
    int i = 0, j = 0;
    u32 id = 0, dlc = 0, len = 0;

    /* 获取发送数据长度 */
    u32 can_send_dlc = FCanSetDlcLen(frame_p->candlc);
        
    /* 标准帧数据转换为dlc */
    /* id */
    id = FCAN_IDR_ID1_SET(frame_p->canid & CAN_SFF_MASK);
    if (frame_p->canid & CAN_RTR_FLAG)
    {
        id |= FCAN_IDR_SRR_MASK;
    }

    /* dlc */
    /* CAN-FD协议 标准帧 */
    if (instance_p->use_canfd == TRUE)
    {
        printf("\n enter if (instance_p->use_canfd == TRUE)\n");

        dlc = ((can_send_dlc << FCANFD_IDR1_SDLC_SHIFT) | FTCANFD_IDR_PAD_MASK);
        dlc |= FTCANFD_ID1_FDL_MASK;
        frame_p->flags |= CANFD_BRS;
        if (frame_p->flags & CANFD_BRS)
        {
            dlc |= FTCANFD_ID1_BRS_MASK;
        }
        if (frame_p->flags & CANFD_ESI)
        {
            dlc |= FTCANFD_ID1_ESI_MASK;
        }
        id |= dlc;
        buf[len++] = be32_to_cpu(id);
    }

    /* 数据帧 */
    if ( !(frame_p->canid & CAN_RTR_FLAG) )
    {
        printf("\n enter if ( !(frame_p->canid & CAN_RTR_FLAG) )\n");
        j = 0;
        for (i = frame_p->candlc; i > 0; i -= 4)
        {
            buf[len++] = *(u32 *)(frame_p->data + j);
            j += 4;
        }

        if (i > 0)
        {
            buf[len++] = *(u32 *)(frame_p->data + j);
        }
    }

    return len;
}

FError FCanSend(FCanCtrl *instance_p, FCanFrame *frame_p)
{
    u32 len;
    int i = 0;
    u32 buf[ ((FCAN_DATA_LENGTH / 4) + 2) ] = {0};
    uintptr base_address = instance_p->config.base_address;

    /* 将can数据转化为对应的帧格式 */
    len = FCanFrameToBuf(instance_p, frame_p, buf);
    for (i = 0; i < len; i++)
    {
        printf("\n enter send \n");
        FCAN_WRITE_REG32(base_address, FCAN_TX_FIFO_OFFSET, buf[i]);
    }
    
    return FCAN_SUCCESS;
}

static FError FCanSetTiming(FCanCtrl *instance_p, FCanBaudrateConfig *bittiming_p, FCanSegmentType target_segment)
{
    u32 reg_val = 0;
    u32 transfer_enable;
    uintptr base_address = instance_p->config.base_address;

    /* Setting Baud Rate prescalar value in BRPR Register */
    reg_val = (bittiming_p->brp - 1) << 16;
    reg_val |= (bittiming_p->prop_seg - 1) << 2;
    reg_val |= (bittiming_p->phase_seg1 - 1) << 5;
    reg_val |= (bittiming_p->phase_seg2 - 1) << 8;
    reg_val |= (bittiming_p->sjw - 1);

    transfer_enable = (FCAN_READ_REG32(base_address, FCAN_CTRL_OFFSET) & FCAN_CTRL_XFER_MASK);
    if (transfer_enable)
    {
        FCAN_CLEARBIT(base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
    }

    if (reg_val)
    {
        if (target_segment == FCAN_DATA_SEGMENT)
        {
            FCAN_WRITE_REG32(base_address, FCAN_DAT_RATE_CTRL_OFFSET, reg_val);
        }
        else
        {
            FCAN_WRITE_REG32(base_address, FCAN_ARB_RATE_CTRL_OFFSET, reg_val);
        }
    }
    else
    {
        return FCAN_FAILURE;
    }

    return FCAN_SUCCESS;
}

FError FCanBaudrateSet(FCanCtrl *instance_p, FCanBaudrateConfig *baudrate_p)
{
    FCanSegmentType segment = baudrate_p->segment;
    u32 baudrate = baudrate_p->baudrate;
    u32 sample_point = baudrate_p->sample_point;
    FError ret = FCAN_SUCCESS;
    FCanBaudrateConfig timing_config;
    memset(&timing_config, 0, sizeof(timing_config));

    if (baudrate_p->auto_calc == TRUE)
    {
        ret = FCanCalcBittiming(&timing_config, baudrate, sample_point, segment);
        if (ret != FCAN_SUCCESS)
        {
            return FCAN_FAILURE;
        }

        ret = FCanSetTiming(instance_p, &timing_config, segment);
        if (ret != FCAN_SUCCESS)
        {
            return FCAN_FAILURE;
        }
    }

    return ret;
}

/**
 * @name: FCanEnable
 * @msg:  Enable or disable can.
 * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
 * @param {boolean} enable, TRUE-enable canfd, FALSE-disable canfd.
 * @return err code information, FCAN_SUCCESS indicates success，others indicates failed
 */
FError FCanEnable(FCanCtrl *instance_p, boolean enable)
{

    uintptr base_addr = instance_p->config.base_address;
    if (enable == TRUE)
    {
        FCAN_SETBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
    }
    else
    {
        FCAN_CLEARBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
    }

    return FCAN_SUCCESS;
}

void FCanIdMaskFilterEnable(FCanCtrl *instance_p)
{
    FCanConfig *config_p;
    config_p = &instance_p->config;
    FCAN_SETBIT(config_p->base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_AIME_MASK);
}

FError FCanIdMaskFilterSet(FCanCtrl *instance_p, FCanIdMaskConfig *id_mask_p)
{
    u32 filter_index = id_mask_p->filter_index;
    uintptr base_address = instance_p->config.base_address;
    u32 id_reg_offset = 0;
    u32 mask_reg_offset = 0;
    u32 id = 0;
    u32 mask = 0;

    switch (filter_index)
    {
        case 0:
            id_reg_offset = FCAN_ACC_ID0_OFFSET;
            mask_reg_offset = FCAN_ACC_ID0_MASK_OFFSET;
            break;
        case 1:
            id_reg_offset = FCAN_ACC_ID1_OFFSET;
            mask_reg_offset = FCAN_ACC_ID1_MASK_OFFSET;
            break;
        case 2:
            id_reg_offset = FCAN_ACC_ID2_OFFSET;
            mask_reg_offset = FCAN_ACC_ID2_MASK_OFFSET;
            break;
        case 3:
            id_reg_offset = FCAN_ACC_ID3_OFFSET;
            mask_reg_offset = FCAN_ACC_ID3_MASK_OFFSET;
            break;
        default:
            return FCAN_FAILURE;
    }

    if (id_mask_p->type == FCAN_STANDARD_FRAME)
    {
        id = id_mask_p->id << FCAN_ACC_IDN_SHIFT;
        mask = id_mask_p->mask << FCAN_ACC_IDN_SHIFT;
    }
    else
    {
        id = id_mask_p->id;
        mask = id_mask_p->mask;
    }
    
    FCAN_WRITE_REG32(base_address, id_reg_offset, id);
    FCAN_WRITE_REG32(base_address, mask_reg_offset, mask);

    return FCAN_SUCCESS;
}

/**
 * @name: FCanFdEnable
 * @msg:  Enable or disable can fd.
 * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
 * @param {boolean} enable, TRUE-enable canfd, FALSE-disable canfd.
 * @return err code information, FCAN_SUCCESS indicates success，others indicates failed
 */
FError FCanFdEnable(FCanCtrl *instance_p, boolean enable)
{
    uintptr base_addr = instance_p->config.base_address;

    instance_p->use_canfd = TRUE;
    FCAN_SETBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_FDCRC_MASK | FCAN_CTRL_IOF_MASK);

    return FCAN_SUCCESS;
}

/**
 * @name: FCanSetMode
 * @msg:  Set the transmit mode, Monitor or Normal
 * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
 * @param {u32} tran_mode,parameters of target mode,0 Monitor mode,1 Normal mode
 * @return err code information, FCAN_SUCCESS indicates success，others indicates failed
 */
FError FCanSetMode(FCanCtrl *instance_p , u32 tran_mode)
{
    uintptr base_addr = instance_p->config.base_address;

    FCAN_SETBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);

    return FCAN_SUCCESS;
}
